#include "ScaleformGFxValue.h"
#include "sfse_common/Errors.h"

Scaleform::GFx::Value::~Value()
{
	CleanManaged();
}

void Scaleform::GFx::Value::AddManaged(void)
{
	if(IsManaged())
		CALL_MEMBER_FN(objectInterface, ObjectAddRef)(this, data.obj);
}

void Scaleform::GFx::Value::CleanManaged(void)
{
	if(IsManaged())
	{
		CALL_MEMBER_FN(objectInterface, ObjectRelease)(this, data.obj);

		objectInterface = NULL;
		type = kType_Undefined;
	}
}

void Scaleform::GFx::Value::SetUndefined(void)
{
	CleanManaged();

	type = kType_Undefined;
}

void Scaleform::GFx::Value::SetNull(void)
{
	CleanManaged();

	type = kType_Null;
}

void Scaleform::GFx::Value::SetBool(bool value)
{
	CleanManaged();

	type = kType_Bool;
	data.boolean = value;
}

void Scaleform::GFx::Value::SetNumber(double value)
{
	CleanManaged();

	type = kType_Number;
	data.number = value;
}

void Scaleform::GFx::Value::SetInt(s32 value)
{
	CleanManaged();

	type = kType_Int;
	data.s32 = value;
}
void Scaleform::GFx::Value::SetUInt(u32 value)
{
	CleanManaged();

	type = kType_UInt;
	data.u32 = value;
}

void Scaleform::GFx::Value::SetString(const char * value)
{
	CleanManaged();

	type = kType_String;
	data.string = value;
}

bool Scaleform::GFx::Value::GetBool(void) const
{
	switch(GetType())
	{
		case kType_Bool:	return data.boolean;
		case kType_Number:	return data.number != 0;
		case kType_Int:		return data.s32 != 0;
		case kType_UInt:	return data.u32 != 0;
		default: HALT("Value::GetBool: bad type"); return false;
	}
}

const char * Scaleform::GFx::Value::GetString(void) const
{
	if(GetType() != kType_String)
		return NULL;

	if(IsManaged())
		return *data.managedString;
	else
		return data.string;
}

double Scaleform::GFx::Value::GetNumber(void) const
{
	switch(GetType())
	{
		case kType_Int:		return (double)data.s32;
		case kType_UInt:	return (double)data.u32;
		case kType_Number:	return data.number;
		case kType_Bool:	return data.boolean ? 1 : 0;
		default:			HALT("Value::GetNumber: bad type"); return 0;
	}
}

s32 Scaleform::GFx::Value::GetInt(void) const
{
	switch(GetType())
	{
		case kType_Int:		return data.s32;
		case kType_UInt:	return (s32)data.u32;
		case kType_Number:	return (s32)data.number;
		case kType_Bool:	return data.boolean ? 1 : 0;
		default:			HALT("Value::GetInt: bad type"); return 0;
	}
}

u32 Scaleform::GFx::Value::GetUInt(void) const
{
	switch(GetType())
	{
		case kType_Int:		return (u32)data.s32;
		case kType_UInt:	return data.u32;
		case kType_Number:	return (u32)data.number;
		case kType_Bool:	return data.boolean ? 1 : 0;
		default:			HALT("Value::GetUInt: bad type"); return 0;
	}
}

bool Scaleform::GFx::Value::HasMember(const char * name)
{
	return CALL_MEMBER_FN(objectInterface, HasMember)(data.obj, name);
}

bool Scaleform::GFx::Value::SetMember(const char * name, Value * value)
{
	return CALL_MEMBER_FN(objectInterface, SetMember)(data.obj, name, value, IsDisplayObject());
}

bool Scaleform::GFx::Value::GetMember(const char * name, Value * value)
{
	return CALL_MEMBER_FN(objectInterface, GetMember)(data.obj, name, value, IsDisplayObject());
}

bool Scaleform::GFx::Value::Invoke(const char * name, Value * result, Value * args, u32 numArgs)
{
	return CALL_MEMBER_FN(objectInterface, Invoke)(data.obj, result, name, args, numArgs, IsDisplayObject());
}

bool Scaleform::GFx::Value::CreateEmptyMovieClip(Value* pValue, const char* instanceName, s32 depth)
{
	return CALL_MEMBER_FN(objectInterface, CreateEmptyMovieClip)(data.obj, pValue, instanceName, depth);
}

bool Scaleform::GFx::Value::AttachMovie(Value* pValue, const char* symbolName, const char* instanceName, s32 depth, const void * initArgs)
{
	return CALL_MEMBER_FN(objectInterface, AttachMovie)(data.obj, pValue, symbolName, instanceName, depth, initArgs);
}

u32 Scaleform::GFx::Value::GetArraySize()
{
	return CALL_MEMBER_FN(objectInterface, GetArraySize)(data.obj);
}

bool Scaleform::GFx::Value::SetArraySize(u32 size)
{
	return CALL_MEMBER_FN(objectInterface, SetArraySize)(data.obj, size);
}

bool Scaleform::GFx::Value::GetElement(u32 index, Value * value)
{
	return CALL_MEMBER_FN(objectInterface, GetElement)(data.obj, index, value);
}

bool Scaleform::GFx::Value::PushBack(const Value& value)
{
	return CALL_MEMBER_FN(objectInterface, PushBack)(data.obj, value);
}

bool Scaleform::GFx::Value::PopBack(Value * value)
{
	return CALL_MEMBER_FN(objectInterface, PopBack)(data.obj, value);
}

void Scaleform::GFx::Value::VisitElements(ObjectInterface::ArrayVisitor * visitor, u32 idx, s32 count)
{
	CALL_MEMBER_FN(objectInterface, VisitElements)(data.obj, visitor, idx, count);
}

bool Scaleform::GFx::Value::GetText(Value * value, bool html)
{
	return CALL_MEMBER_FN(objectInterface, GetText)(data.obj, value, html);
}

bool Scaleform::GFx::Value::SetText(const char * text, bool html)
{
	return CALL_MEMBER_FN(objectInterface, SetText)(data.obj, text, html);
}

void Scaleform::GFx::Value::VisitMembers(ObjectInterface::ObjVisitor * visitor)
{
	CALL_MEMBER_FN(objectInterface, VisitMembers)(data.obj, visitor, IsDisplayObject());
}

bool Scaleform::GFx::Value::GetDisplayInfo(DisplayInfo * displayInfo)
{
	return CALL_MEMBER_FN(objectInterface, GetDisplayInfo)(data.obj, displayInfo);
}

bool Scaleform::GFx::Value::SetDisplayInfo(DisplayInfo * displayInfo)
{
	return CALL_MEMBER_FN(objectInterface, SetDisplayInfo)(data.obj, displayInfo);
}

bool Scaleform::GFx::Value::GotoLabeledFrame(const char * frameLabel, bool stop)
{
	return CALL_MEMBER_FN(objectInterface, GotoAndPlayL)(data.obj, frameLabel, stop);
}
